#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>

#include "tree.h"

GtkTreeStore *_empty_tree() {
    GtkTreeStore *data;
    GtkTreeIter iter;

    // define the number of columns and typifies them
    data=gtk_tree_store_new(
        1,              // number of columns
        G_TYPE_STRING   // the tree
    );

    // set the data
    gtk_tree_store_append(data, &iter, NULL);
    gtk_tree_store_set( // a folder
        data, &iter,
        0, "<empty tree>",   // filename
        -1
    );

    return data;
}

int _run_ST_tree(GtkTreeStore *store, GtkTreeIter *parent, sST *tree, unsigned int numdirs, gint *columns, GValue *values) {
    GtkTreeIter iter;
    static unsigned int i;

    while(tree) {
        g_value_set_static_string(&values[0], tree->name);
        for(i=0; i<numdirs; i++)
            g_value_set_static_string(&values[i+1], FS_NAMES[tree->files[i].status]);

        gtk_tree_store_append(store, &iter, parent);
        gtk_tree_store_set_valuesv(store, &iter, columns, values, numdirs+1);

        if(tree->child)
            _run_ST_tree(store, &iter, tree->child, numdirs, columns, values);

        tree=tree->next;
    }
}

GtkTreeStore *_ST_tree(sSynq *synq) {
    GtkTreeStore *store;
    GType *types;
    GValue *values;
    gint *columns;
    unsigned int i;

    types=(GType *)malloc((1+synq->dirs.numdirs)*sizeof(GType));
    if(!types) return NULL;
    values=(GValue *)calloc(1+synq->dirs.numdirs, sizeof(GValue));
    if(!values) return NULL;
    columns=(gint *)malloc((1+synq->dirs.numdirs)*sizeof(gint));
    if(!columns) return NULL;

    for(i=0; i<1+synq->dirs.numdirs; i++) {
        types[i]=G_TYPE_STRING;
        g_value_init (&values[i], types[i]);
        columns[i]=i;
    }

    store=gtk_tree_store_newv(1+synq->dirs.numdirs, types);

    _run_ST_tree(store, NULL, synq->tree, synq->dirs.numdirs, columns, values);

    free(types);
    free(values);
    free(columns);

    return store;
}

sTree *tree_new_empty() {
    sTree *tree=(sTree *)calloc(1, sizeof(sTree));
    if(!tree) return NULL;

    tree_update_data(tree, _empty_tree(), 0);

    return tree;
}

int tree_update(sTree *tree, sSynq *synq) {
    if(!tree || !synq) return 1;

    tree_update_data(tree, _ST_tree(synq), synq->dirs.numdirs);

    return 0;
}

int tree_update_data(sTree *tree, GtkTreeStore *data, unsigned int n_paths) {
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    unsigned int i;
    gchar pathname[20];

    if(!tree) return 1;

    tree->data=data;
    tree->n_paths=n_paths;

    if(tree->widget) {
        gtk_tree_view_set_model(GTK_TREE_VIEW(tree->widget), GTK_TREE_MODEL(data));

        // remove existing columns
        GList *clist=gtk_tree_view_get_columns(GTK_TREE_VIEW(tree->widget));
        GList *rem=clist;
        while(clist) {
            gtk_tree_view_remove_column(GTK_TREE_VIEW(tree->widget), clist->data);
            clist=clist->next;
        }
        g_list_free(rem);
    }
    else {
        tree->widget=gtk_tree_view_new_with_model(GTK_TREE_MODEL(data));
    }

    // ce qui va "dessiner" le contenu de la cellule
    renderer=gtk_cell_renderer_text_new();

    // première colonne : arbre
    column=gtk_tree_view_column_new_with_attributes(
        "Tree",     // nom de la colonne
        renderer,   // renderer de cellule
        "text", 0,  // la valeur de la propriété "text" de ce renderer va être celle de la première colonne : 0
        NULL
    );
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree->widget), column);

    // colonnes suivantes : dossiers
    for(i=0; i<n_paths; i++) {
        sprintf(pathname, "Path%d", i+1);

        column=gtk_tree_view_column_new_with_attributes(
            pathname,   // nom de la colonne
            renderer,   // renderer de cellule
            "text", i+1,  // la valeur de la propriété "text" de ce renderer va être celle de la i-ème colonne
            NULL
        );
        gtk_tree_view_append_column(GTK_TREE_VIEW(tree->widget), column);
    }

    return 0;
}

void tree_delete(sTree *tree) {
    if(!tree) return;

    if(tree->widget)
        gtk_widget_destroy(tree->widget);
    if(tree->data)
        gtk_tree_store_clear(tree->data);

    free(tree);
}

